package com.xf.common.core.authe;

import com.xf.common.core.domain.PassWordToken;
import com.xf.common.core.domain.TokenInfo;
import org.apache.commons.codec.binary.Base64;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.DefaultResponseErrorHandler;
import org.springframework.web.client.RestTemplate;
import org.springframework.beans.factory.annotation.Value;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;

/**
 * @author JoeyLiu
 * @create 2022-04-02 9:22
 */
@Service
public class Oauth2ServiceImpl implements Oauth2Service {

    @Resource
    private RestTemplate restTemplate;

    @Resource
    private Oauth2UrlConfig oauth2UrlConfig;

    @Value("${dmp.oauth2.organizationId}")
    private String organizationId;

    @Override
    public TokenInfo login(PassWordToken passwordToken) throws Exception {
        return queryAccessTokenInfo(passwordToken);
    }

    @Override
    public TokenInfo refresh(String passwordToken) throws Exception {
        return refreshToken(passwordToken);
    }


    public TokenInfo queryAccessTokenInfo(PassWordToken tokenRequest) {
        DefaultResponseErrorHandler handler = new DefaultResponseErrorHandler();
        restTemplate.setErrorHandler(handler);
        MultiValueMap<String, String> header = buildAouthHeader(organizationId);
        String url = String.format(oauth2UrlConfig.getAuthorizationtoken(), tokenRequest.getLoginName(), tokenRequest.getPassword());
        ResponseEntity<TokenInfo> exchange = restTemplate.exchange(url, HttpMethod.POST, new HttpEntity(header), TokenInfo.class);
        return exchange.getBody();
    }

    public TokenInfo refreshToken(String refreshToken) {
        DefaultResponseErrorHandler handler = new DefaultResponseErrorHandler();
        restTemplate.setErrorHandler(handler);
        MultiValueMap<String, String> header = buildAouthHeader(organizationId);
        String url = String.format(oauth2UrlConfig.getRefreshToken(), refreshToken);
        ResponseEntity<TokenInfo> exchange = restTemplate.exchange(url, HttpMethod.POST, new HttpEntity(header), TokenInfo.class);
        return exchange.getBody();
    }


    private MultiValueMap<String, String> buildAouthHeader(String tenantId) {
        MultiValueMap<String, String> headers = new LinkedMultiValueMap();
        List<String> auth = new ArrayList();
        String plainCreds = String.format("%s:%s", oauth2UrlConfig.getClientId(), oauth2UrlConfig.getClientSecret());
        byte[] plainCredsBytes = plainCreds.getBytes();
        byte[] base64CredsBytes = Base64.encodeBase64(plainCredsBytes);
        String base64Creds = new String(base64CredsBytes);
        auth.add("Basic " + base64Creds);
        headers.put("Authorization", auth);
        headers.add("organizationId", tenantId);
        return headers;
    }
}
